﻿using System;
using System.Xml;
using System.Xml.Schema;
using XmlStudio.DataLayer;
using XmlStudio.Models.Events;
using System.Xml.XPath;
using System.Collections.Generic;
using System.ComponentModel;

namespace XmlStudio.Interfaces {
    /// <summary>
    /// Internal extension to <see cref="IXmlModel"/> interface. Adds internal methods which
    /// manipulate with the xmlModel etc.
    /// </summary>
    internal interface IXmlModelWithNotifications : IXmlModel {
        #region Properties
        /// <summary>
        /// Gets the <see cref="XmlDocument"/> associated with the xmlModel.
        /// </summary>
        XmlDocument XmlDocument { get; }

        /// <summary>
        /// Gets or sets the <see cref="XmlDocumentType"/>.
        /// </summary>
        new XmlDocumentType DocumentType { get; set; }

        /// <summary>
        /// Reference to the <see cref="IBigXmlReader"/> used for reading the document.
        /// </summary>
        IBigXmlReader Reader { get; }

        /// <summary>
        /// Gets or sets the root element of the document.
        /// </summary>
        BigXmlNode Root { get; set; }

        /// <summary>
        /// Gets the collection of nodes loaded in the xmlModel.
        /// </summary>
        IDictionary<IXPathNavigable, BigXmlNodeInternal> Nodes { get; }

        int TotalNodeCount { get; set; }
        #endregion

        #region Methods
        void RemoveRootNode();

        /// <summary>
        /// Invokes the <see cref="IXmlModel.NodeExpanded"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnNodeExpanded(NodeExpandedEventArgs<BigXmlNode> e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.NodeCollapsed"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnNodeCollapsed(NodeCollapsedEventArgs<BigXmlNode> e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.RawXmlChanged"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnRawXmlChanged(RawXmlChangedEventArgs e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.DocumentNameRequired"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnDocumentNameRequired(DocumentNameRequiredEventArgs e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.NodeUpdated"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnNodeUpdated(NodeUpdatedEventArgs<BigXmlNode> e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.NodeAdded"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnNodeAdded(NodeAddedEventArgs<BigXmlNode> e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.RootElementAdded"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnRootElementAdded(RootElementAddedEventArgs<BigXmlNode> e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.NodeRemoved"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnNodeRemoved(NodeRemovedEventArgs<BigXmlNode> e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.AttributeAdded"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnAttributeAdded(AttributeAddedEventArgs<BigXmlNode, IBigXmlAttribute> e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.AttributeRemoved" /> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnAttributeRemoved(AttributeRemovedEventArgs<BigXmlNode, IBigXmlAttribute> e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.Closing"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnClosing(EventArgs e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.Closed"/> event.
        ///  </summary>
        /// <param name="e">The event data.</param>
        void OnClosed(EventArgs e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.Saving"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnSaving(EventArgs e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.Saved"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnSaved(EventArgs e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.Validating" /> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnValidating(ValidationEventArgs e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.StatusUpdated"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnStatusUpdated(StatusUpdatedEventArgs e);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.NodesSelected"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnNodesSelected(NodesSelectedEventArgs<BigXmlNode> e);

        /// <summary>
        /// Adds node to the collection of nodes loaded in xmlModel.
        /// </summary>
        /// <param name="xmlNode"><see cref="IXPathNavigable"/> as key to the collection.</param>
        /// <param name="node"><see cref="BigXmlNodeInternal"/> as value.</param>
        void AddNode(IXPathNavigable xmlNode, BigXmlNodeInternal node);

        /// <summary>
        /// Removes node from the collection of loaded nodes.
        /// </summary>
        /// <param name="xmlNode">Node to remove.</param>
        void RemoveNode(IXPathNavigable xmlNode);

        /// <summary>
        /// Removes node with the subtree from the collection of loaded nodes.
        /// </summary>
        /// <param name="xmlNode">Root node of the subtree to remove from the collection.</param>
        void RemoveNodeWithChildren(XmlNode xmlNode);

        /// <summary>
        /// Adds node with the subtree to the collection of loaded nodes.
        /// </summary>
        /// <param name="node">Root node of the subtree to add.</param>
        void AddNodeWithChildren(BigXmlNodeInternal node);

        /// <summary>
        /// Invokes the <see cref="IXmlModel.SubtreeUpdated"/> event.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnSubtreeUpdated(SubtreeUpdatedEventArgs<BigXmlNode> e);

        /// <summary>
        /// Invoked when root element has been replaced by some other element.
        /// </summary>
        /// <param name="e">The event data.</param>
        void OnRootElementChanged(RootElementChangedEventArgs e);

        void OnProgressChanged(ProgressChangedEventArgs e);

        void OnSaveCompleted(EventArgs e);

        /// <summary>
        /// Synchronizes collection of loaded nodes with the actual tree. This is helper method.
        /// </summary>
        /// <remarks>Sometimes happens that nodes actually loaded and those in the collection get out of sync so this method
        ///  helps to keep it in order.</remarks>
        void SyncNodes();

        /// <summary>
        /// Invokes the PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">Name of the changed property.</param>
        void OnPropertyChanged(string propertyName);

        /// <summary>
        /// Sets the modified property.
        /// </summary>
        /// <param name="modified">Value to set.</param>
        void SetModified(bool modified);
        #endregion
    }
}
